package com.meshnetics.gb.stack.mac.type;

import com.meshnetics.gb.type.DataType;
import com.meshnetics.gb.type.DataValue;
import com.meshnetics.gb.type.impl.ByteUtils;
import com.meshnetics.gb.type.impl.custom.StructureDataType;
import com.meshnetics.gb.type.impl.zcl.TypeUInt;
import com.meshnetics.gb.type.impl.zcl.UInt;

import java.nio.ByteBuffer;

/**
 * WRITE DESCRIPTION HERE
 *
 * @author AKovylin
 */
public class TypeDataAddress extends StructureDataType {
    public static final TypeDataAddress TYPE = new TypeDataAddress();

    public static final int ADDR_MODE_PANID = 0x00;
    public static final int ADDR_MODE_SHORT = 0x02;
    public static final int ADDR_MODE_LONG = 0x03;

    TypeDataAddress() {
        super("macAddress",
                new String[]{
                        "panID",
                        "shortAddress",
                        "longAddress"},
                new DataType[]{
                        TypeUInt.UINT_16,
                        TypeUInt.UINT_16,
                        TypeUInt.UINT_64});
    }

    public DataValue fromObject(Object value) {
        throw new UnsupportedOperationException("not implemented yet");
        // todo reimplement
    }

    public DataValue deserialize(ByteBuffer bb) {
        ByteUtils.ensureNotNull(bb);
        ByteUtils.ensureCapacity(bb, 1);
        byte addrMode = bb.get();
        DataAddress res;
        UInt panid;
        UInt address;
        switch (addrMode) {
            case ADDR_MODE_PANID:
                ByteUtils.ensureCapacity(bb, 2, 3);
                panid = (UInt) TypeUInt.UINT_16.deserialize(bb);
                res = new DataAddress(panid);
                break;
            case ADDR_MODE_SHORT:
                ByteUtils.ensureCapacity(bb, 4, 5);
                panid = (UInt) TypeUInt.UINT_16.deserialize(bb);
                address = (UInt) TypeUInt.UINT_16.deserialize(bb);
                res = new DataAddress(panid, address);
                break;
            case ADDR_MODE_LONG:
                ByteUtils.ensureCapacity(bb, 10, 11);
                panid = (UInt) TypeUInt.UINT_16.deserialize(bb);
                address = (UInt) TypeUInt.UINT_64.deserialize(bb);
                res = new DataAddress(panid, address);
                break;
            default:
                throw new IllegalArgumentException("invalid addressing mode " + addrMode);
        }
        return res;
    }
}
